import React, { PureComponent } from 'react'
import { connect } from '@umijs/max'
import { Form, Input, message, Modal, notification, Popconfirm, Spin, Tabs, TreeSelect, Upload } from 'antd'
import list2tree from 'list2tree'
import { ExclamationCircleFilled } from '@ant-design/icons'
import Tools from '@/utils/Tools'
import { HufuTreeTitle, ProTable, ProTableOptions, ProTree, searchTreeListByName } from '@/components'
import { TreeIcon } from '../../../../components'
import styles from './index.less'
import {
  deleteTask,
  devDirChange,
  dropResource,
  getDirTree,
  getResourceDetail,
  getTrees,
  saveDir,
  saveResource
} from './api'
import { getProjectId, SUAN_PAN } from '@/utils/https'

const Bus = Tools.Bus
const { Item } = Form
const { TextArea } = Input
const { Dragger } = Upload
const { TabPane } = Tabs
const isDir = (nodeType) => [0, 1, 2, 3, 4].includes(nodeType)
const getNavTreeDataFunc = list2tree({
  idKey: 'id',
  parentIdKey: 'pid',
  newKey: {
    key: 'id',
    value: 'id',
    title: 'name',
  },
})

/**
 * 数据开发任务类型 ----------------------------nodeType-----------------------------------
 * 0：普通目录
 * 1：工作流程目录
 * 2：数据集成目录
 * 3：数据开发目录
 * 4：数据质量目录
 * 10：资源
 * 11：函数
 * 12：开始节点
 * 13：sql
 * 14：mr
 * 15：impala
 * 16：shell
 * 17：python2
 * 18：python3
 * 19：pyspark
 * 20：离线同步
 * 21：接口采集
 * 22：数据质量
 * */

@connect(({ scriptDev }) => ({ ...scriptDev }))
export default class DataDevTree extends PureComponent {
  constructor(props) {
    super(props)
    this.state = {
      // expandArr: [],
      modifyId: null,
      isShowTask: false,
      navListSpinning: false,
      isShowFiles: false,
      searchValue: '',
      treeOption: [],
      fItem: null,
      cItem: null,
      fileDownloadUrl: '',
      filePath: '',
      originalFilename: '',
      isShowDetail: false,
      selectedKeys: [],
      treeLists: [],
      treeDataNew: [],
    }

    this.taskForm = React.createRef()
    this.fileForm = React.createRef()
    this.detailForm = React.createRef()
  }

  componentDidMount() {
    this.refresh()
    Bus.addListener('ShowFileModal', this.showTaskModal)
    Bus.addListener('RefreshDevTree', this.refresh)
  }

  componentWillUnmount() {
    Bus.removeListener('ShowFileModal', this.showTaskModal)
    Bus.removeListener('RefreshDevTree', this.refresh)
  }

  // 获取树状列表
  getTreeList = () => {
    this.setState({ navListSpinning: true })
    getTrees({ id: 3 }).then(
      (res) => {
        this.setState({
          navListSpinning: false,
          treeLists: res,
          treeDataNew: getNavTreeDataFunc(res),
        })
      },
      (error) => {
        this.setState({ navListSpinning: false })
      },
    )
  }

  // 获取目录选项列表
  getDirTreeOption = () => {
    getDirTree({ id: 3 }).then(
      (res) => {
        if (res && res[0]) {
          const { childs } = res[0]
          this.setState({
            treeOption: childs,
          })
        } else {
          this.setState({
            treeOption: [],
          })
        }
      },
      (error) => {
        console.log(error)
      },
    )
  }

  // 打开新建目录弹窗
  showFilesModal = (id) => {
    this.fileForm.current?.resetFields()
    this.setState({
      modifyId: null,
      isShowFiles: true,
    }, () => {
      if (id) {
        this.fileForm.current.setFieldsValue({ pid: id })
      }
    })
  }

  // 编辑打开新建目录弹窗
  editFilesModal = (item) => {
    this.fileForm.current?.resetFields()
    this.setState({
      modifyId: item.id,
      isShowFiles: true,
    }, () => {
      if (item) {
        this.fileForm.current.setFieldsValue({
          pid: item.pid == '3' ? undefined : item.pid,
          name: item.name,
        })
      }
    })
  }

  // 打开上传资源弹窗
  showTaskModal = (item, pid) => {
    this.taskForm.current?.resetFields()
    this.setState({
      modifyId: item ? item.id : null,
      isShowTask: true,
    }, () => {
      if (item) {
        this.taskForm.current.setFieldsValue({
          pid: (item.pid && item.pid != '3') ? item.pid : undefined,
          resName: item.name,
          desc: item.remark,
        })
      } else if (pid) {
        this.taskForm.current.setFieldsValue({ pid })
      }
    })
  }

  // 刷新
  refresh = () => {
    this.getTreeList()
    this.getDirTreeOption()
  }

  renderTreeNodes = (data) => {
    const tempArr = []
    data.map((item) => {
      const {
        name, id, nodeType,
      } = item
      const defaultIconFun = props => {
        const { selectedKeys } = this.state
        if (selectedKeys && selectedKeys[0] == props.data.key) {
          return props.expanded ? <i className="iconfont-colour2 icon-wenjianjia-dakaihover" /> : <i className="iconfont-colour2 icon-wenjianjia-morenhover" />
        }
        return props.expanded ? <i className="iconfont-colour2 icon-wenjianjia-dakai" /> : <i className="iconfont-colour2 icon-wenjianjia-moren" />
      }
      const icon = item.nodeType == 0 ? defaultIconFun : <TreeIcon color="green" iconName="icon-tuceng" />
      const tempObj = {
        icon,
        key: id,
        nodeType,
      }
      tempObj.title = (
        <HufuTreeTitle
          title={name}
          key={item.id}
          icon
          operations={[
            isDir(item.nodeType) ? (
              <span
                key={`newDir${item.id}`}
                onClick={() => this.showFilesModal(item.id)}
              >
                新建目录
              </span>
            ) : null,
            isDir(item.nodeType) ? (
              <span
                key={`new${item.id}`}
                onClick={() => this.showTaskModal(null, item.id)}
              >
                上传资源
              </span>
            ) : null,
            <span
              key={`edit${item.id}`}
              onClick={() => {
                isDir(item.nodeType) ? this.editFilesModal(item) : this.showTaskModal(item)
              }}
            >
              编辑
            </span>,
            <span
              key={`del${item.id}`}
              onClick={() => {
                Modal.confirm({
                  title: '确认要删除这个任务吗？',
                  icon: <ExclamationCircleFilled />,
                  content: '删除后数据将无法恢复，请谨慎操作',
                  okText: '删除',
                  cancelText: '取消',
                  okButtonProps: {
                    danger: true,
                  },
                  onOk: () => {
                    this.setState({ navListSpinning: true })
                    deleteTask({ id: item.id }).then(
                      (res) => {
                        message.success('删除成功')
                        this.refresh()
                      },
                      (error) => {
                        this.setState({ navListSpinning: false })
                      },
                    )
                  },
                })
              }}
            >
              删除
            </span>,
          ]}
        />
      )
      if (item.children) {
        tempObj.children = this.renderTreeNodes(item.children)
      }
      tempArr.push(tempObj)
    })
    return tempArr
  }

  onDragEnter = (opt) => {

    // if ([0, 3].indexOf(opt.node.props.data.nodeType) > -1) {
    //   this.setState({
    //     expandArr: opt.expandedKeys,
    //   })
    // }
  }

  onDrop = (opt) => {
    if (!opt.dropToGap) {
      this.setState(
        {
          cItem: opt.dragNode.props.data,
          fItem: opt.node.props.data,
        },
        this.catalogChange,
      )
    } else {
      this.setState(
        {
          cItem: opt,
        },
        // this.datadevDirSort,
      )
    }
  }

  // 拖动
  catalogChange = () => {
    const cItem = this.state.cItem
    const fItem = this.state.fItem
    const noChange = (isDir(fItem.nodeType)
      && [fItem.nodeType, 13, 14, 15, 16, 17, 18, 19].includes(cItem.nodeType))
      || (isDir(fItem.nodeType) && fItem.nodeType == cItem.nodeType)
      || (isDir(fItem.nodeType) && cItem.nodeType == 20 && fItem.nodeType == 2)
      || (isDir(fItem.nodeType) && cItem.nodeType == 21 && fItem.nodeType == 2)
      || (isDir(fItem.nodeType) && cItem.nodeType == 3 && fItem.nodeType == 3)
    if (noChange) {
      devDirChange({
        pid: fItem.key,
        id: cItem.key,
      }).then(
        (res) => {
          message.success('修改成功')
          // 当修改完成后，由于可以跨层级拖动，所以为了保险所有的工作流都要刷新
          this.refresh()
        },
        (error) => {
          console.log(error)
        },
      )
    } else {
      message.warning('此文件不能移动到此目录下')
    }
  }

  // 新建目录确认
  filesOnOk = () => {
    this.fileForm.current.validateFields().then(values => {
      this.setState({ navListSpinning: true })
      if (this.state.modifyId) {
        values.id = this.state.modifyId
      }
      if (!values.pid) values.pid = 3
      saveDir(values).then(
        (res) => {
          message.success(this.state.modifyId ? '修改目录成功' : '新建目录成功')
          this.setState({
            isShowFiles: false,
            navListSpinning: false,
          }, () => {
            this.refresh()
          })
        },
        (error) => {
          this.setState({ navListSpinning: false })
        },
      )
    })
  }

  // 上传资源确认
  taskOnOk = () => {
    this.taskForm.current.validateFields().then(values => {
      // 创建formData对象
      const {
        fileDownloadUrl, filePath, originalFilename, modifyId,
      } = this.state
      // 新建时必须要先上传文件
      if (!modifyId && (!fileDownloadUrl || fileDownloadUrl == '')) {
        message.warning('请先上传文件')
        return
      }
      this.setState({ navListSpinning: true })
      const postObj = {
        nodeName: values.resName,
        pid: values.pid || 3,
        desc: values.desc,
      }
      if (fileDownloadUrl && fileDownloadUrl != '') {
        postObj.fileDownloadUrl = fileDownloadUrl
        postObj.filePath = filePath
        postObj.originalFilename = originalFilename
      }
      if (this.state.modifyId) {
        postObj.nodeId = this.state.modifyId
      }
      saveResource(postObj).then(
        (res) => {
          message.success(this.state.modifyId ? '上传资源成功' : '编辑资源成功')
          this.setState({
            isShowTask: false,
            navListSpinning: false,
            fileDownloadUrl: '',
            filePath: '',
            originalFilename: '',
          }, () => {
            this.refresh()
          })
        },
        (error) => {
          this.setState({ navListSpinning: false })
        },
      )
    })
  }

  // 树状列表选择回调
  onSelect = (selectedKeys) => {
    this.setState({
      selectedKeys,
    }, () => {
      if (selectedKeys.length > 0) {
        const { treeLists } = this.state
        const obj = treeLists.find((item) => item.id == selectedKeys[0])
        if (obj && obj.nodeType == 10) {
          this.setState({ navListSpinning: true })
          getResourceDetail({
            nodeId: obj.id,
            resourceName: obj.name,
          }).then(
            (res) => {
              this.setState({
                modifyId: obj.id,
                isShowDetail: true,
                navListSpinning: false,
              }, () => {
                this.detailForm.current.setFieldsValue(res)
              })
            },
            (error) => {
              this.setState({ navListSpinning: false })
            },
          )
        }
      }
    })
  }

  // 删除资源
  delResource = (record) => {
    this.setState({ navListSpinning: true })
    dropResource({
      nodeId: record.nodeId,
      name: record.fileName,
    }).then(
      (res) => {
        message.success('删除资源成功')
        this.setState({
          navListSpinning: false,
        })
      },
      (error) => {
        this.setState({ navListSpinning: false })
      },
    )
  }

  render() {
    const {
      treeOption, searchValue, isShowDetail, selectedKeys, treeLists, treeDataNew,
    } = this.state
    const {
      title,
    } = this.props
    return (
      <div
        className={`${styles.script_dev}`}
      // style={{ display: this.props.navKey == 0 ? 'block' : 'none' }}
      >
        <Spin spinning={this.state.navListSpinning}>
          <div className={styles.datadev_tree_box}>
            <ProTree
              onExpand={this.onExpand}
              // expandedKeys={this.state.expandArr}
              selectedKeys={selectedKeys}
              showSearch
              onDragEnter={this.onDragEnter}
              onDrop={this.onDrop}
              // draggable
              onSelect={this.onSelect}
              title={title || '目录'}
              operations={[
                <i
                  key="1"
                  className="iconfont icon-xinjianwenjianjia"
                  onClick={() => this.showFilesModal(null)}
                />,
                <i
                  key="2"
                  className="iconfont icon-shangchuan"
                  onClick={() => this.showTaskModal(null)}
                />,
              ]}
              renderTreeNodes={this.renderTreeNodes}
              treeData={treeDataNew}
              ref={(dev) => (this.tree = dev)}
              search={(name) => {
                const searchTree = searchTreeListByName(
                  name,
                  treeLists,
                )
                const treeDataNews = getNavTreeDataFunc(
                  searchTree.result,
                )
                this.setState(
                  {
                    treeDataNew: treeDataNews,
                  },
                  () => {
                    this.tree.onExpand(searchTree.fatchIds)
                  },
                )
              }}
            />
          </div>
        </Spin>
        <Modal
          title={this.state.modifyId ? '修改目录' : '新建目录'}
          visible={this.state.isShowFiles}
          confirmLoading={this.state.navListSpinning}
          cancelText="取消"
          okText="保存"
          onOk={this.filesOnOk}
          onCancel={() => {
            this.setState({
              isShowFiles: false,
            })
          }}
          maskClosable={false}
        >
          <div className={styles.file_box}>
            <Form
              ref={this.fileForm}
              labelCol={{ span: 5 }}
              wrapperCol={{ span: 19 }}
              autoComplete="off"
            >
              <Item
                label="目录名称"
                name="name"
                rules={[
                  { required: true, message: '请输入目录名称' },
                ]}
              >
                <Input placeholder="请输入目录名称" />
              </Item>
              <Item
                label="父级目录"
                name="pid"
              >
                <TreeSelect
                  allowClear
                  showSearch
                  getPopupContainer={(triggerNode) => triggerNode.parentNode}
                  // dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
                  treeData={treeOption}
                  placeholder="请选择父级目录"
                  treeDefaultExpandAll
                  filterTreeNode={(input, treeNode) => treeNode.name.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                  fieldNames={{
                    label: 'name', value: 'id', children: 'childs',
                  }}
                />
              </Item>
            </Form>
          </div>
        </Modal>
        <Modal
          title="上传资源"
          confirmLoading={this.state.navListSpinning}
          visible={this.state.isShowTask}
          cancelText="取消"
          okText="上传"
          onOk={this.taskOnOk}
          onCancel={() => {
            this.setState({
              isShowTask: false,
            })
          }}
          maskClosable={false}
        >
          <div className={styles.file_box}>
            <Dragger
              style={{
                height: '200px',
                marginBottom: '0.16rem',
              }}
              accept=".jar"
              onChange={(info) => {
                if (info.file.status != 'uploading') {
                  console.log(info.file, info.fileList)
                }
                if (info.file.status == 'done') {
                  if (info.file.response) {
                    const { data, msg, status } = info.file.response
                    if (status == 200) {
                      message.success('上传成功！')
                      this.setState({
                        fileDownloadUrl: data.fileDownloadUrl,
                        filePath: data.filePath,
                        originalFilename: data.originalFilename,
                      })
                    } else {
                      notification.warning({
                        message: `${info.file.name} 上传失败.`,
                        description: msg,
                        style: {
                          paddingRight: 20,
                        },
                      })
                    }
                  }
                } else if (info.file.status == 'error') {
                  console.log(info.file, info.fileList)
                }
              }}
              action={`${SUAN_PAN}/api/v1/offlineDev/upload`}
              name="file"
              headers={{ 'X-Project-Id': getProjectId() }}
              maxCount={1}
            >
              <p className="ant-upload-drag-icon">
                <i className="iconfont icon-cunchu" />
              </p>
              <p className="ant-upload-text">将文件拖拽至此，或单击直接上传</p>
              <p className="ant-upload-hint">支持扩展名：jar</p>
            </Dragger>
            <Form
              ref={this.taskForm}
              labelCol={{ span: 5 }}
              wrapperCol={{ span: 19 }}
              autoComplete="off"
            >
              <Item
                label="资源名称"
                name="resName"
                rules={[
                  { required: true, message: '请输入资源名称' },
                ]}
              >
                <Input placeholder="请输入资源名称" />
              </Item>
              <Item
                label="父级目录"
                name="pid"
              >
                <TreeSelect
                  allowClear
                  showSearch
                  getPopupContainer={(triggerNode) => triggerNode.parentNode}
                  // dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
                  treeData={treeOption}
                  placeholder="请选择父级目录"
                  treeDefaultExpandAll
                  filterTreeNode={(input, treeNode) => treeNode.name.toLowerCase().indexOf(input.toLowerCase()) >= 0}
                  fieldNames={{
                    label: 'name', value: 'id', children: 'childs',
                  }}
                />
              </Item>
              <Item
                label="描述"
                name="desc"
              >
                <TextArea
                  placeholder="请输入描述"
                  rows={3}
                />
              </Item>
            </Form>
          </div>
        </Modal>
        <Modal
          title="资源详情"
          confirmLoading={this.state.navListSpinning}
          visible={isShowDetail}
          footer={null}
          onCancel={() => {
            this.setState({
              isShowDetail: false,
            })
          }}
          width={720}
        >
          <Tabs
            defaultActiveKey="1"
          >
            <TabPane
              tab="基础信息"
              key="1"
            >
              <Form
                ref={this.detailForm}
                labelCol={{ span: 5 }}
                wrapperCol={{ span: 19 }}
                autoComplete="off"
              >
                <Item
                  label="资源名称"
                  name="name"
                >
                  <Input disabled />
                </Item>
                <Item
                  label="责任人"
                  name="userName"
                >
                  <Input disabled />
                </Item>
                <Item
                  label="创建时间"
                  name="uploadTime"
                >
                  <Input disabled />
                </Item>
                <Item
                  label="修改时间"
                  name="updateTime"
                >
                  <Input disabled />
                </Item>
                <Item
                  label="描述"
                  name="desc"
                >
                  <Input disabled />
                </Item>
              </Form>
            </TabPane>
            <TabPane
              tab="历史版本"
              key="2"
            >
              <ProTable
                showQuickJumper={false}
                showSizeChanger={false}
                pagination={false}
                url="/api/v1/offlineDev/resource/listResource"
                query={{ nodeId: this.state.modifyId }}
                columns={[
                  {
                    title: '文件名称',
                    dataIndex: 'fileName',
                    key: 'fileName',
                    width: '20%',
                    ellipsis: true,
                  },
                  {
                    title: '描述',
                    dataIndex: 'desc',
                    key: 'desc',
                    width: '20%',
                    ellipsis: true,
                  },
                  {
                    title: '操作者',
                    dataIndex: 'userName',
                    key: 'userName',
                    width: '20%',
                    ellipsis: true,
                  },
                  {
                    title: '上传时间',
                    dataIndex: 'uploadTime',
                    key: 'uploadTime',
                    width: '20%',
                    ellipsis: true,
                  },
                  {
                    title: '操作',
                    dataIndex: 'action',
                    key: 'action',
                    width: '20%',
                    ellipsis: true,
                    render: (text, record, index) => (
                      <ProTableOptions>
                        <span>
                          <a
                            href={record.fileDownloadUrl}
                            download
                          >下载
                          </a>
                        </span>
                        <Popconfirm
                          title="确认要删除吗？"
                          onConfirm={() => { this.delResource(record) }}
                          okText="确定"
                          cancelText="取消"
                        >
                          <span>删除</span>
                        </Popconfirm>
                      </ProTableOptions>
                    ),
                  },
                ]}
              />
            </TabPane>
          </Tabs>
        </Modal>
      </div>
    )
  }
}
